package patternmining.model.construction;

import temp.MethodNameResolver;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import org.antlr.runtime.RecognitionException;
import patternmining.model.construction.ModelData;

/** An instance of JavaSourceGroup bundles source files that constitutes a project that shall be modeled by a
 *  joined graph.
 * 
 * Usage:
 *  JavaSourceGroup sourceGroup = new JavaSourceGroup();
 *  File sourceItem = new File("MyClass.java");
 *  sourceGroup.addFile(sourceItem); 
 *  ... // eventually add more source files to the group
 *  ModelData modelData = sourceGroup.modelData();
 *  // procede with the modelData to construct a graph
 * 
 * @see ModelGraphBuilder.java
 * 
 * @version 1.0, 10.05.2008
 * @author Holger Wiehen
 */
public class JavaSourceGroup extends Source{

    List<JavaSourceFile> sources;
    
    public JavaSourceGroup(){
        sources = new LinkedList<JavaSourceFile>();
    }
    
    public ModelData modelData(){
        ModelData modelData = new ModelData();
        ModelData globalModelData = new ModelData();
        try{
            //1.step: prepare the consecutive steps by construction of the AST for every source file in this group
            for (JavaSourceFile sourceFile : sources){
                sourceFile.first_construct_AST();
            }
            
            //2.step: construct a "package -> member" mapping shared by all java source files defined by this souce group
            //        (preparation to know what types are imported by a import statement)
            for (JavaSourceFile sourceFile : sources){
                sourceFile.second_completePackageIndex();
            }
            
            //3.pass: extract some preliminar information to be able to resolve short type names to its qualified version 
            //        and atribute names to it's types as well as overloaded method names to a unique version
            //        in the processing of the final step of extraction of model relevant information (4.pass) 
            for (JavaSourceFile sourceFile : sources){
                sourceFile.third_constructMemberTable();
            }

            Project tempProject = Project.getInstance();
            PackageIndex tempPackageIndex = PackageIndex.getInstance();

            //4.pass: extract the elements to be modeled from the source files forming the source group to be modeled by a joined graph
            for (JavaSourceFile sourceFile : sources){
                modelData = sourceFile.forth_extractModelData();
                //globalModelData.addModelData(modelData);
            }
        }
        catch( IOException e ){ System.out.println( e.toString()); }
        catch( RecognitionException e ){ System.out.println( e.toString()); }
        
        return globalModelData;
    }
    
    public void addFile(File file) throws IOException, WrongFileTypeException{
        if ( file.isFile() && isJavaSourceFile(file) )
            sources.add( new JavaSourceFile(file));
        if ( !isJavaSourceFile(file) )
            throw new WrongFileTypeException("File " + file.getCanonicalPath() + " is not a JavaSourceFile");
    }
    
    public void addDirectory(File directory) throws IOException, WrongFileTypeException{
        if( directory.isDirectory() ){
            File[] files = directory.listFiles();
            for( File file : files){
                addFile(file);
            }
        }
    }
    
    public void addDirectoryRecursivly(File rootDirectory) throws IOException, WrongFileTypeException{
        //adds all the files contained under this directory and arbitrarily nested subdirectories to a flat list of files
        if(rootDirectory.isDirectory()){
            File currentDirectory;
            File[] currentMembers;
            Queue<File> uninspectedDirectories = new ArrayDeque<File>();
            uninspectedDirectories.add(rootDirectory);
            while( !uninspectedDirectories.isEmpty() ){
                currentDirectory = uninspectedDirectories.remove();
                currentMembers = currentDirectory.listFiles();
                for( File currentFile : currentMembers ){
                    if( currentFile.isFile() )
                        addFile(currentFile);
                    if( currentFile.isDirectory() )
                        uninspectedDirectories.add(currentFile);
                }
            }
       }
       
    }

}
